package com.cnswhy.cloud.server.core.appservice.impl;

import com.cnswhy.cloud.common.core.mybatis.conditions.Wraps;
import com.cnswhy.cloud.common.core.utils.CnswhyUtil;
import com.cnswhy.cloud.common.core.utils.SystemClockUtil;
import com.cnswhy.cloud.common.logging.uitls.MDCUtil;
import com.cnswhy.cloud.common.rabbitmq.service.MessageService;
import com.cnswhy.cloud.common.redis.annotation.RedisLock;
import com.cnswhy.cloud.common.redis.model.LockTimeoutStrategy;
import com.cnswhy.cloud.common.redis.service.IdGeneratorService;
import com.cnswhy.cloud.common.redis.service.RedisService;
import com.cnswhy.cloud.server.common.entity.constant.AmqpExchange;
import com.cnswhy.cloud.server.common.entity.enumeration.PayType;
import com.cnswhy.cloud.server.common.entity.enumeration.TransType;
import com.cnswhy.cloud.server.common.entity.enumeration.WalletType;
import com.cnswhy.cloud.server.common.entity.mq.ConsumerValueAddMsg;
import com.cnswhy.cloud.server.common.entity.mq.CreateIotTerminalMQ;
import com.cnswhy.cloud.server.common.entity.mq.ShopOrderSplitMsg;
import com.cnswhy.cloud.server.common.entity.mq.SpellMsg;
import com.cnswhy.cloud.server.core.appservice.AppSpellOrderService;
import com.cnswhy.cloud.server.core.constant.RedisConstant;
import com.cnswhy.cloud.server.core.entity.*;
import com.cnswhy.cloud.server.core.oem.OemService;
import com.cnswhy.cloud.server.core.service.CustomerUpgradeMenuService;
import com.cnswhy.cloud.server.core.service.CustomerUpgradeTransOrderService;
import com.cnswhy.cloud.server.core.service.ShopOrderDetailService;
import com.cnswhy.cloud.server.core.service.customer.CustomerService;
import com.cnswhy.cloud.server.core.service.shop.ShopOrderService;
import com.cnswhy.cloud.server.core.service.shop.ShopProductService;
import com.cnswhy.cloud.server.core.service.spell.BuyBackOrderService;
import com.cnswhy.cloud.server.core.service.spell.SpellOrderService;
import com.cnswhy.cloud.server.core.service.spell.SpellPriceService;
import com.cnswhy.cloud.server.core.wallet.WalletService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class AppSpellOrderServiceImpl implements AppSpellOrderService {
    @Autowired
    RedisService redisService;
    @Autowired
    SpellOrderService spellOrderService;
    @Autowired
    CustomerService customerService;
    @Autowired
    WalletService walletService;
    @Autowired
    IdGeneratorService idGeneratorService;
    @Autowired
    MessageService messageService;
    @Autowired
    OemService oemService;
    @Autowired
    SpellPriceService spellPriceService;
    @Autowired
    ShopOrderDetailService shopOrderDetailService;
    @Autowired
    ShopProductService shopProductService;
    @Autowired
    CustomerUpgradeTransOrderService customerUpgradeTransOrderService;
    @Autowired
    CustomerUpgradeMenuService customerUpgradeMenuService;
    /*@Autowired
    OemService oemService;
    @Autowired
    SpellInfoService spellInfoService;*/

    @Override
    public void upgradeOrder(String outNo, String orderNum, PayType payType) {
        CustomerUpgradeTransOrder customerUpgradeTransOrder = customerUpgradeTransOrderService.getOne(Wraps.<CustomerUpgradeTransOrder>lbQ().eq(CustomerUpgradeTransOrder::getOrderId,orderNum));
        CustomerUpgradeMenu customerUpgradeMenu = customerUpgradeMenuService.getById(customerUpgradeTransOrder.getMenuId());
        customerUpgradeTransOrder.setExpired(0);
        customerUpgradeTransOrder.setStatus(2);
        customerUpgradeTransOrder.setStartDay(SystemClockUtil.getLocalDateTime());
        customerUpgradeTransOrder.setEndDay(SystemClockUtil.getLocalDateTime().plusDays(customerUpgradeMenu.getDays()));
        customerUpgradeTransOrderService.updateById(customerUpgradeTransOrder);
    }

    @Override
    @RedisLock(name = "notifySpellOrder", waitTime = 10, leaseTime = 60, keys = {"#orderNum"}, lockTimeoutStrategy = LockTimeoutStrategy.FAIL_FAST)
    public void notifySpellOrder(String outNo, String orderNum, PayType payType) {
        SpellOrder order = spellOrderService.getOne(Wraps.<SpellOrder>lbQ().eq(SpellOrder::getPayOrderNum,orderNum));
        if(order == null){
            return;
        }
        if(oemService.isChaoRenGou()){
            if(!Integer.valueOf(2).equals(order.getStatus()) && !Integer.valueOf(0).equals(order.getSendStatus())){
                return;
            }
        }else{
            if(!Integer.valueOf(1).equals(order.getStatus())){
                return;
            }
        }
        updateOrder(order,outNo,payType);
        SpellMsg spellMsg = SpellMsg.builder().id(order.getId()).build();
        spellMsg.setTraceId(MDCUtil.getTraceId());
        messageService.sendQueueByObject(AmqpExchange.SPELL_MESSAGE, spellMsg);

    }

    private void updateOrder(SpellOrder order,String outNo,PayType payType){
        if(oemService.isChaoRenGou()){
            order.setSendStatus(1);
        }else{
            order.setStatus(2);
        }
        order.setPayType(payType.getVal());
        order.setIsPrivilege(2);
        order.setTransactionId(outNo);
        if(!oemService.isChaoRenGou()){
            SpellPrice spellPrice = spellPriceService.getById(order.getPriceId());
            order.setSpellOrderId(spellPrice.getNewSpellOrderId());
        }
        spellOrderService.saveOrUpdate(order);
    }

    @Autowired
    BuyBackOrderService buyBackOrderService;

    @Override
    @RedisLock(name = "notifyPay", waitTime = 10, leaseTime = 60, keys = {"#orderNum"}, lockTimeoutStrategy = LockTimeoutStrategy.FAIL_FAST)
    public void notifyPay(String orderNum, String returnOrder) {
        BuyBackOrder queryByOrderNum = buyBackOrderService.getOne(Wraps.<BuyBackOrder>lbQ().eq(BuyBackOrder::getOrderNum, orderNum));
        /*if (!(queryByOrderNum.getStatus().equals("1"))) {
            return;
        }*/
        if(!Integer.valueOf(1).equals(queryByOrderNum.getStatus())){
            return;
        }
        queryByOrderNum.setStatus(2);
        queryByOrderNum.setReturnOrderNum(returnOrder);
        buyBackOrderService.updateById(queryByOrderNum);

        //更新拼团信息为已回购
        /*Long spellOrderId = queryByOrderNum.getSpellOrderId();
        SpellOrder order = spellOrderService.getById(spellOrderId);
        order.setSendStatus(5);
        spellOrderService.updateById(order);
        Customer customer = customerService.queryById(order.getCustomerId());
        CustomerWallet customerWallet = walletService.checkAndCreate(customer.getId(), WalletType.BALANCE, CnswhyUtil.getFen(customer.getAvailableBalance()));
        walletService.add(customerWallet.getCustomerId(), WalletType.BALANCE, TransType.BUY_BACK_CHARGE, CnswhyUtil.getFen(queryByOrderNum.getOrderPrice()), TransType.COUPON_CHARGE.getCode() + queryByOrderNum.getOrderNum());*/
        /*Customer customer = customerService.queryById(order.getCustomerId());
        CustomerWallet customerWallet = walletService.checkAndCreate(customer.getId(), WalletType.COUPON, CnswhyUtil.getFen(customer.getCoupon()));
        walletService.add(customerWallet.getCustomerId(), WalletType.COUPON, TransType.COUPON_CHARGE, CnswhyUtil.getFen(queryByOrderNum.getOrderPrice()), TransType.COUPON_CHARGE.getCode() + queryByOrderNum.getOrderNum());*/
    }

    @Autowired
    ShopOrderService shopOrderService;

    @RedisLock(name = "saveOrderNotify", waitTime = 10, leaseTime = 60, keys = {"#payOrderNo"}, lockTimeoutStrategy = LockTimeoutStrategy.FAIL_FAST)
    @Override
    public void saveOrderNotify(String payOrderNo, String transactionNo) {
        List<ShopOrder> orderList = new ArrayList<ShopOrder>();

        // 订单类型标志位：true 表示单个订单支付，false表示联合订单支付
        boolean orderTypeFlag = false;
        ShopOrder queryShopOrder = shopOrderService.getOne(Wraps.<ShopOrder>lbQ().eq(ShopOrder::getChannelOrderId,payOrderNo));
        //if (!(queryShopOrder.getStatus().equals("1"))) {
        if(!Integer.valueOf(1).equals(queryShopOrder.getStatus())){
            log.info("该订单已经回调成功");
            return;
        }
        // 整个订单支付成功
        if (payOrderNo.startsWith("P")) {
            // 根据支付订单号，查询商家订单列表
            //ShopOrder orders = shopOrderService.getOne(Wraps.<ShopOrder>lbQ().eq(ShopOrder::getPayOrderNo,payOrderNo));


            // 删除redis订单过期队列中的记录

            redisService.hdel(RedisConstant.SHOP_PRODUCT_ORDER, queryShopOrder.getId() + "");
            redisService.hdel(RedisConstant.SHOP_PRODUCT_PAY_ORDER, queryShopOrder.getPayOrderNo());

            orderList.add(queryShopOrder);
        }
        // 单个商户订单支付成功
        else {
            orderTypeFlag = true;
            //ShopOrder order = shopOrderService.getOne(Wraps.<ShopOrder>lbQ().eq(ShopOrder::getPayOrderNo,payOrderNo));
            // 删除redis订单过期队列中的记录
            redisService.hdel(RedisConstant.SHOP_PRODUCT_ORDER, queryShopOrder.getId() + "");

            // 删除redis中待支付订单
            String field = String
                    .valueOf(redisService.hget(RedisConstant.SHOP_PRODUCT_PAY_ORDER, queryShopOrder.getPayOrderNo()));
            String orders[] = field.split("\\|")[0].split(",");
            // 若只有一个支付订单，则直接删除
            if (orders.length == 1) {
                redisService.hdel(RedisConstant.SHOP_PRODUCT_PAY_ORDER, queryShopOrder.getPayOrderNo());
            }
            // 若有多个订单，只支付了其中一笔，则只删掉支付的那笔订单
            else {
                StringBuffer sb = new StringBuffer();
                for (String o : orders) {
                    if (!o.equals(queryShopOrder.getId() + "")) {
                        if (sb.length() > 0) {
                            sb.append(",");
                        }
                        sb.append(o);
                    }
                }
                redisService.hset(RedisConstant.SHOP_PRODUCT_PAY_ORDER, queryShopOrder.getPayOrderNo(), sb.toString());
            }

            orderList.add(queryShopOrder);
        }

        for (ShopOrder order : orderList) {
            ShopOrder shopOrder = updateShopOrder(order.getId(),2,transactionNo,order.getOrderNo(),orderTypeFlag);
            // 检查是否物联设备
            List<ShopOrderDetail> shopOrderDetailList = shopOrderDetailService.list(Wraps.<ShopOrderDetail>lbQ().eq(ShopOrderDetail::getOrderId,shopOrder.getId()));
            for(ShopOrderDetail shopOrderDetail : shopOrderDetailList){
                ShopProduct shopProduct = shopProductService.getById(shopOrderDetail.getProductId());
                if(Integer.valueOf(1).equals(shopProduct.getIsIotTerminal())){
                    //是物联设备
                    CreateIotTerminalMQ createIotTerminalMQ = CreateIotTerminalMQ.builder().customerId(shopOrder.getCustomerId()).productId(shopProduct.getId()).build();
                    messageService.sendQueueByObject(AmqpExchange.CREATE_IOT_TERMINAL_MESSAGE, createIotTerminalMQ);

                }
            }
            //分销通知
            ShopOrderSplitMsg spellMsg = ShopOrderSplitMsg.builder().id(order.getId()).build();
            spellMsg.setTraceId(MDCUtil.getTraceId());
            messageService.sendQueueByObject(AmqpExchange.SHOP_ORDER_SPLIT_MESSAGE, spellMsg);
            messageService.sendQueueByObject(AmqpExchange.CONSUMER_VALUE_MESSAGE, ConsumerValueAddMsg.builder().customerId(order.getCustomerId()).orderId(order.getPayOrderNo()).transAmt(order.getOrderPrice()).build());

        }
    }

    private ShopOrder updateShopOrder(Long id,int status, String returnOrder, String orderNo,Boolean orderTypeFlag){
        ShopOrder entity = new ShopOrder();
        entity.setId(id);
        entity.setStatus(status);
        entity.setPayTime(SystemClockUtil.getLocalDateTime());
        entity.setReturnOrderNo(returnOrder);
        // 如果是单个订单支付，则支付订单号就是订单号
        if (orderTypeFlag) {
            entity.setPayOrderNo(orderNo);
        }
        shopOrderService.updateById(entity);
        return entity;
    }
}